﻿using System;

namespace OmniKits.Extensions
{
    /// <summary>
    /// Provides methods those help processing DataTime.
    /// </summary>
    public static class DateTimeExtensions
    {
#pragma warning disable 1591

        #region ByGivenTicks

        /// <summary>
        /// Lower the DateTime value's precision to be given ticks.
        /// </summary>
        public static DateTime ByGivenTicks(this DateTime value, long ticks)
        {
            // 先除后乘，舍弃掉不足的部分。

            return new DateTime(value.Ticks / ticks * ticks, value.Kind);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be given ticks, nullable.
        /// </summary>
        public static DateTime? ByGivenTicks(this DateTime? value, long ticks)
        {
            // 同上。

            if (value.HasValue)
                return new DateTime(value.Value.Ticks / ticks * ticks, value.Value.Kind);
            return null;
        }

#if !PCL
        /// <summary>
        /// Lower the DateTime value's precision to be given ticks.
        /// </summary>
        public static DateTime ByGivenTicks(this DateTime value, long ticks, MidpointRounding mode)
        {
            // 先除后乘，舍弃掉不足的部分。

            decimal time = value.Ticks;
            time = time / ticks;

            return new DateTime((long)Math.Round(time, mode) * ticks, value.Kind);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be given ticks, nullable.
        /// </summary>
        public static DateTime? ByGivenTicks(this DateTime? value, long ticks, MidpointRounding mode)
        {
            // 同上。

            if (value.HasValue)
                return value.Value.ByGivenTicks(ticks, mode);
            //return new DateTime(value.Value.Ticks / ticks * ticks, value.Value.Kind);
            return null;
        }
#endif

#pragma warning disable 1591
        #endregion

        #region BySecond

        /// <summary>
        /// Lower the DateTime value's precision to be second.
        /// </summary>
        public static DateTime BySecond(this DateTime value)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerSecond);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be second, nullable.
        /// </summary>
        public static DateTime? BySecond(this DateTime? value)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerSecond);
        }

#if !PCL
        /// <summary>
        /// Lower the DateTime value's precision to be second.
        /// </summary>
        public static DateTime BySecond(this DateTime value, MidpointRounding mode)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerSecond, mode);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be second, nullable.
        /// </summary>
        public static DateTime? BySecond(this DateTime? value, MidpointRounding mode)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerSecond, mode);
        }
#endif

        #endregion

        #region ByMillisecond

        /// <summary>
        /// Lower the DateTime value's precision to be millisecond.
        /// </summary>
        public static DateTime ByMillisecond(this DateTime value)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerMillisecond);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be millisecond, nullable.
        /// </summary>
        public static DateTime? ByMillisecond(this DateTime? value)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerMillisecond);
        }

#if !PCL
        /// <summary>
        /// Lower the DateTime value's precision to be millisecond.
        /// </summary>
        public static DateTime ByMillisecond(this DateTime value, MidpointRounding mode)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerMillisecond, mode);
        }
        /// <summary>
        /// Lower the DateTime value's precision to be millisecond, nullable.
        /// </summary>
        public static DateTime? ByMillisecond(this DateTime? value, MidpointRounding mode)
        {
            return value.ByGivenTicks(TimeSpan.TicksPerMillisecond, mode);
        }
#endif

        #endregion
    }
}
